﻿// Copyright (c) Appeon. All rights reserved.
// Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. 
// You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0.

using System;
using System.IO;
using System.Text.Json;
using System.Text.Encodings.Web;
using System.Text.Json.Serialization;

namespace SnapObjects.Data
{
    internal class SysJsonProvider : IJsonProvider
    {
        private readonly JsonSerializerOptions _options = new JsonSerializerOptions
        { 
            Encoder = JavaScriptEncoder.UnsafeRelaxedJsonEscaping,
            PropertyNameCaseInsensitive = true
        };

        private readonly JsonSerializerOptions _SerializeOptions = new JsonSerializerOptions
        {
            Encoder = JavaScriptEncoder.UnsafeRelaxedJsonEscaping,
            PropertyNameCaseInsensitive = true
        };

        public SysJsonProvider()
        {
            _SerializeOptions.Converters.Add(new SysFloatConvert());
        }

        public INodeReader GetNodeReader(string raw)
        {
            return SysJsonNodeReader.Parse(raw);
        }

        public INodeReader GetNodeReader(Stream stream)
        {
            if (stream == null)
            {
                throw new ArgumentNullException(nameof(stream));
            }

            return SysJsonNodeReader.Parse(stream);
        }

        public INodeWriter GetNodeWriter()
        {
            return new SystJsonNodeWriter();
        }

        public INodeWriter GetNodeWriter(Stream stream)
        {
            if (stream == null)
            {
                throw new ArgumentNullException(nameof(stream));
            }

            return new SystJsonNodeWriter(stream);
        }

        public string SerializeObject(object value)
        {
            if (value == null)
            {
                return "null";
            }

            return JsonSerializer.Serialize(value, _SerializeOptions);
        }

        public T DeserializeObject<T>(string value)
        {
            if (value == null)
            {
                throw new ArgumentNullException(nameof(value));
            }
            else if (String.IsNullOrWhiteSpace(value))
            {
                return default;
            }

            return JsonSerializer.Deserialize<T>(value, _options);
        }

        public object DeserializeObject(string value, Type type)
        {
            if (value == null)
            {
                throw new ArgumentNullException(nameof(value));
            }
            else if (String.IsNullOrWhiteSpace(value))
            {
                return default;
            }

            if (type == null)
            {
                throw new ArgumentNullException(nameof(type));
            }

            return JsonSerializer.Deserialize(value, type, _options);
        }
    }

    internal class SysFloatConvert : JsonConverter<float>
    {
        public override float Read(ref Utf8JsonReader reader, Type typeToConvert, JsonSerializerOptions options)
        {
            return reader.GetSingle();
        }

        public override void Write(Utf8JsonWriter writer, float value, JsonSerializerOptions options)
        {
            var tmpValue = value.ToString("G17");

            writer.WriteRawValue(tmpValue);
        }
    }
}